#   创建时间：2021-05-25  14:55
#   目的：将圆圈和方块视为碰撞模型。
#   参考：
#       _8_pygame_demo_color_dictWithClass_3_Multi_Group_ExOK.py
#       _4_pygame_demo_Part3_OK.py
import pygame,pygame.locals
import sys,os,time
COLOR_BLACK = (0,0,0)
COLOR_WHITE = (255,255,255)
COLOR_RED = (255,0,0)
COLOR_BKG = COLOR_WHITE

WORKPLACE_PATH = os.getcwd()
IMAGE_PATH = f'{WORKPLACE_PATH}\COLOR_BLOCK_PNG\\'  #[S0]

WINDOW_X_MAX = 400                                  #[S0]
WINDOW_Y_MAX = 400                                  #[S0]
DISPLAYSURF = pygame.display.set_mode((WINDOW_X_MAX,WINDOW_Y_MAX))
DISPLAYSURF.fill(COLOR_BKG)
BKG_IMAGE = pygame.image.load(IMAGE_PATH + 'blackBKG.png')  #[S0]

def game_init():
    pygame.init()
    pygame.display.init()
    pygame.font.init()

def refresh_pygame():                   #   这个refresh_pygame()函数要和 pygame.display.update() 一起结合使用。
                                        #   这样程序才不会运行至一半导致崩溃，另外仅有move_ip()而无blit()，也会导致图片不会刷新。
    FPS = 60                            #[S0]
    pygame.time.Clock().tick(FPS)
    for event in pygame.event.get():
        if event.type == pygame.locals.QUIT:
            pygame.quit()
            sys.exit()
    DISPLAYSURF.blit(BKG_IMAGE,(0,0))   #   即背景图片的图层最先刷新，因为后出的blit()加载图片 会覆盖上一个blit()加载图片
                                        #   如果将此处注释掉 ， 则 那几个 IRO_BLOCK 中的 move() 会产生拖影。
                                        #   如果将背景图片的刷新给放入IRO_BLOCK的load()中，就会出现只显示 最后的blit()加载图片
#-------------------------------------------------------------------------------------------------------------------------
#以下为 代表 鼓 的字典，类，和实例化。
PAD_BEATS_DICT = {
    '0':{
        'PAD_DICT_ID':0,
        'PAD_NAME':'SNARE_HEAD_BEAT',
        'PAD_NOTE_NUMBER':38,
        'X_SIZE':40,
        'Y_SIZE':40,
        'START_POSITION':(0,WINDOW_Y_MAX/2),
        'START_TIME_s':0,
        'PAD_IMAGE':pygame.image.load(IMAGE_PATH + 'circlePS.png')
    }
}

class PAD_BEATS_CIRCLE(pygame.sprite.Sprite):
    def __init__(self,DICT_ID,NAME,NOTE_NUMBER,\
                      X,Y,ST_POSITION,\
                      ST_TIME,IMAGE):
        super().__init__()
        self.PAD_DICT_ID = DICT_ID
        self.PAD_NAME = NAME
        self.PAD_NOTE_NUMBER = NOTE_NUMBER
        self.X_SIZE = X
        self.Y_SIZE = Y
        self.START_POSITION = ST_POSITION
        self.START_TIME_s = ST_TIME
        self.PAD_IMAGE = IMAGE

        self.SURF = pygame.Surface((self.X_SIZE,self.Y_SIZE))
        self.rect = self.SURF.get_rect(center = self.START_POSITION)    #   使用碰撞模型时，这个命名一定要为小写的rect

    def load(self):
        self.START_TIME_s = time.time()
        DISPLAYSURF.blit(self.PAD_IMAGE,self.rect)
        #print(f'{self.PAD_NAME} 出现时间为 ： ',self.START_TIME_s)
    
    def move(self):
        self.rect.move_ip(0,0)
        #print(f'{self.PAD_NAME} 的类型为 ：',type(self.rect))
PAD_BEATS_DICT['0'] = PAD_BEATS_CIRCLE(PAD_BEATS_DICT['0']['PAD_DICT_ID'],PAD_BEATS_DICT['0']['PAD_NAME'],PAD_BEATS_DICT['0']['PAD_NOTE_NUMBER'],\
                                  PAD_BEATS_DICT['0']['X_SIZE'],PAD_BEATS_DICT['0']['Y_SIZE'],PAD_BEATS_DICT['0']['START_POSITION'],\
                                  PAD_BEATS_DICT['0']['START_TIME_s'],PAD_BEATS_DICT['0']['PAD_IMAGE'])
#----------------------------------------------------------------------------------------------------------------------------
# 以下为代表 MIDI 的方块字典，类，及实例化。
MIDI_NOTE_DICT = {
    '0':{
        'MIDI_DICT_ID':0,
        'MIDI_NAME':'SNARE_HEAD_MIDI',
        'MIDI_NOTE_NUMBER':38,
        'MIDI_ALIVE_STATE':False,
        'X_SIZE':40,
        'Y_SIZE':40,
        'START_POSITION':(WINDOW_X_MAX,WINDOW_Y_MAX/2),
        'START_TIME_s':0,
        'MOVE_STEP_x': -10,
        'MIDI_IMAGE':pygame.image.load(IMAGE_PATH+'greenBlock.png'),
        'LOAD_FUNCT_STATUES':False
    }
}

class MIDI_NOTE_BLOCK(pygame.sprite.Sprite):
    def __init__(self,DICT_ID,NAME,NOTE_NUMBER,\
                      ALIVE_STATE,X,Y,\
                      ST_POSITION,ST_TIME,STEP,\
                      IMAGE,LOAD_STATUES = False):
        super().__init__()
        self.count_time = 0
        self.MIDI_DICT_ID = DICT_ID
        self.MIDI_NAME = NAME
        self.MIDI_NOTE_NUMBER = NOTE_NUMBER
        self.MIDI_ALIVE_STATE = ALIVE_STATE
        self.X_SIZE = X
        self.Y_SIZE = Y
        self.START_POSITION = ST_POSITION
        self.START_TIME_s = ST_TIME
        self.MOVE_STEP_x = STEP #   沿着X轴方向进行移动
        self.MIDI_IMAGE = IMAGE
        self.LOAD_FUNCT_STATUES = LOAD_STATUES

        self.SURF = pygame.Surface((self.X_SIZE,self.Y_SIZE))
        self.rect = self.SURF.get_rect(center = self.START_POSITION)

    def load(self):
        if len(MIDI_NOTE_DICT) > 0 :
            if self.LOAD_FUNCT_STATUES == False and self.count_time == 0:                     #   若 MIDI_NOTE_DICT 的对象首次出现
                self.count_time += 1
                DISPLAYSURF.blit(self.MIDI_IMAGE,self.rect)
                self.MIDI_ALIVE_STATE = True                          #   则self.MIDI_ALIVE_STATE改为 存活
                self.LOAD_FUNCT_STATUES = True
                print(f'{self.MIDI_NAME}首次出现的时间为 ：',time.time()-PYGAME_START_TIME)
            else :
                DISPLAYSURF.blit(self.MIDI_IMAGE,self.rect)
        else :
            self.count_time = 0

    def move(self):
        if self.LOAD_FUNCT_STATUES == True :
            self.rect.move_ip(self.MOVE_STEP_x,0)
            if self.rect.right < 0 :                            #   若 MIDI_NOTE_DICT 的对象移出 pygame 的窗口，
                self.MIDI_ALIVE_STATE = False                   #   则 self.MIDI_ALIVE_STATE改为 死亡，
                self.LOAD_FUNCT_STATUES = False
                print(f'{self.MIDI_NAME}最后出现的时间为 ：',time.time()-PYGAME_START_TIME)
            else :
                pass
        else :
            pass

MIDI_NOTE_DICT_MAX = 3
for i in range(0,MIDI_NOTE_DICT_MAX) :
    if i == 0:
        MIDI_NOTE_DICT[str(i)] ={
                'MIDI_DICT_ID':i,
                'MIDI_NAME':f'SNARE_HEAD_MIDI_{i}',
                'MIDI_NOTE_NUMBER':38,
                'MIDI_ALIVE_STATE':False,
                'X_SIZE':40,
                'Y_SIZE':40,
                'START_POSITION':(WINDOW_X_MAX,WINDOW_Y_MAX/2),
                'START_TIME_s':0,
                'MOVE_STEP_x': -10,
                'MIDI_IMAGE':pygame.image.load(IMAGE_PATH+'greenBlock.png'),
                'LOAD_FUNCT_STATUES':False
        }
        MIDI_NOTE_DICT[str(i)] = MIDI_NOTE_BLOCK(MIDI_NOTE_DICT[str(i)]['MIDI_DICT_ID'],MIDI_NOTE_DICT[str(i)]['MIDI_NAME'],MIDI_NOTE_DICT[str(i)]['MIDI_NOTE_NUMBER'],\
                                            MIDI_NOTE_DICT[str(i)]['MIDI_ALIVE_STATE'],MIDI_NOTE_DICT[str(i)]['X_SIZE'],MIDI_NOTE_DICT[str(i)]['Y_SIZE'],\
                                            MIDI_NOTE_DICT[str(i)]['START_POSITION'],MIDI_NOTE_DICT[str(i)]['START_TIME_s'],MIDI_NOTE_DICT[str(i)]['MOVE_STEP_x'],\
                                            MIDI_NOTE_DICT[str(i)]['MIDI_IMAGE'],MIDI_NOTE_DICT[str(i)]['LOAD_FUNCT_STATUES'])
    else :
        MIDI_NOTE_DICT[str(i)] ={
        'MIDI_DICT_ID':i,
        'MIDI_NAME':f'SNARE_HEAD_MIDI_{i}',
        'MIDI_NOTE_NUMBER':38,
        'MIDI_ALIVE_STATE':False,
        'X_SIZE':40,
        'Y_SIZE':40,
        'START_POSITION':(WINDOW_X_MAX,WINDOW_Y_MAX/2),
        'START_TIME_s':0,
        'MOVE_STEP_x': i-10,
        'MIDI_IMAGE':pygame.image.load(IMAGE_PATH+'greenBlock.png'),
        'LOAD_FUNCT_STATUES':False
        }
        MIDI_NOTE_DICT[str(i)] = MIDI_NOTE_BLOCK(MIDI_NOTE_DICT[str(i)]['MIDI_DICT_ID'],MIDI_NOTE_DICT[str(i)]['MIDI_NAME'],MIDI_NOTE_DICT[str(i)]['MIDI_NOTE_NUMBER'],\
                                            MIDI_NOTE_DICT[str(i)]['MIDI_ALIVE_STATE'],MIDI_NOTE_DICT[str(i)]['X_SIZE'],MIDI_NOTE_DICT[str(i)]['Y_SIZE'],\
                                            MIDI_NOTE_DICT[str(i)]['START_POSITION'],MIDI_NOTE_DICT[str(i)]['START_TIME_s'],MIDI_NOTE_DICT[str(i)]['MOVE_STEP_x'],\
                                            MIDI_NOTE_DICT[str(i)]['MIDI_IMAGE'],MIDI_NOTE_DICT[str(i)]['LOAD_FUNCT_STATUES'])


print('MIDI_NOTE_DICT = ',MIDI_NOTE_DICT)
#----------------------------------------------------------------------------------------------------------------------------
#以下为pygame.sprite.Group的创建

PAD_BEATS_GROUP = pygame.sprite.Group()
PAD_BEATS_GROUP.add(PAD_BEATS_DICT['0'])

MIDI_NOTE_38_GROUP = pygame.sprite.Group()
for i in range(0,len(MIDI_NOTE_DICT)):
    MIDI_NOTE_38_GROUP.add(MIDI_NOTE_DICT[str(i)])

ALL_ENTITY = pygame.sprite.Group()
ALL_ENTITY.add(PAD_BEATS_DICT['0'])
for i in range(0,len(MIDI_NOTE_DICT)):
    ALL_ENTITY.add(MIDI_NOTE_DICT[str(i)])

#----------------------------------------------------------------------------------------------------------------------------
if __name__ == "__main__":
    game_init()
    
    font = pygame.font.SysFont("Verdana", 60)
    font_small = pygame.font.SysFont("Verdana", 20)
    game_over = font.render("Game Over", True, COLOR_BLACK)

    PYGAME_START_TIME = time.time()
    print('游戏开始时间 ： ',time.ctime(PYGAME_START_TIME))
    SCORE = 0
    while len(MIDI_NOTE_38_GROUP) > 0 :
        # [传统手打方式 START]
        # refresh_pygame()
        # PAD_BEATS_DICT['0'].load()
        # PAD_BEATS_DICT['0'].move()

        # MIDI_NOTE_DICT['0'].load()
        # MIDI_NOTE_DICT['0'].move()
        # pygame.display.update()
        # [传统手打方式 END]
        refresh_pygame()
        scores = font_small.render(str(SCORE), True, COLOR_RED)
        DISPLAYSURF.blit(scores, (10,10))   #   装载    scores  至坐标(10,10)。
        
        for entity in ALL_ENTITY:
            entity.load()
            entity.move()

        if pygame.sprite.spritecollideany(PAD_BEATS_DICT['0'], MIDI_NOTE_38_GROUP) :
            print("pygame.sprite.spritecollideany(PAD_BEATS_DICT['0'], MIDI_NOTE_38_GROUP) = ",pygame.sprite.spritecollideany(PAD_BEATS_DICT['0'], MIDI_NOTE_38_GROUP) )
            SCORE += 1
            print('发生碰撞时的时间 ： ',time.ctime(time.time()))
            MIDI_NOTE_38_GROUP.remove(pygame.sprite.spritecollideany(PAD_BEATS_DICT['0'], MIDI_NOTE_38_GROUP))  #   若检测到碰撞，则删除那个碰撞物
            ALL_ENTITY.remove(pygame.sprite.spritecollideany(PAD_BEATS_DICT['0'], MIDI_NOTE_38_GROUP))
            # if len(MIDI_NOTE_38_GROUP) == 0 :
            #     for entity in ALL_ENTITY :
            #         entity.kill()
            #     pygame.quit()                               #   结束游戏。
            #     sys.exit()
            print('MIDI_NOTE_38_GROUP = ',MIDI_NOTE_38_GROUP)
        pygame.display.update()

    print('游戏结束时间 ： ',time.ctime(time.time()))
